#include <iostream>
#include <ctime>
#include <unistd.h>
#include "Protocol.hpp"
#include "Socket.hpp"
#include "Log.hpp"

using namespace protocol_ns;
using namespace socket_ns;
using namespace log_ns;

int main(int argc, char* args[]) {
    if (argc != 3) {
        LOG(ERROR, "please input the -> ./client、ip and port\n");
        return 0;
    }
    // 获取 ip 和 port 以及 socket
    uint16_t server_port = std::stoi(args[2]);
    std::string server_ip = args[1];

    // 创建sockfd，以及将其连接起来
    ScokSPtr socket = std::make_shared<TcpSocket>();
    if (!socket->BuildCilentSocket(server_port, server_ip)) {
        LOG(FATAL, "connect fail\n");
        return 1;
    }

    srand(time(nullptr) ^ getpid());
    std::string operators("+-*/!^&");

    // 连接成功，现在开始通信
    while (true) {
        // 1. 先创建出需要解决的Request
        int x = rand() % 10, y = rand() % 10;
        usleep(1000 * x * y);
        char oper = operators[y % operators.size()];
        std::shared_ptr<Request> Req = Factory::BuildRequest();
        Req->SetValue(x, y, oper);

        std::string jsonstr;
        // 1. 将数据序列化
        jsonstr = Req->Serialize();

        // 2. 为数据添加报头
        jsonstr = Encode(jsonstr);

        // 3. 将数据发送出去
        std::cout << "jsonstr\n" << jsonstr << std::endl;
        ssize_t n = socket->Send(jsonstr);

        std::cout << "----------------------------------------------" << std::endl;
        // 将发送出去的jsonstr打印出来

        if (n == 0) {
            LOG(ERROR, "send message failed\n");
            exit(1);
        }


        while (true) {
            // 4. 现在开始接收消息
            std::shared_ptr<Responce> Resp = Factory::BuildResponce();
            std::string packagestreamqueue;
            socket->Recv(&packagestreamqueue);

            // 5. 将收到的信息解码
            std::string package = Decode(packagestreamqueue);
            if (package.empty()) continue; 
            // 将解码后的数据打印出来
            std::cout << "package\n" << package << std::endl;

            // 6. 反序列化
            Resp->Deserialize(package);

            // 7. 将数据打印出来
            Resp->PrintResult();

            break;
        }

        sleep(1);
    }

    return 0;
}